// ----------------------------------------------------------------------------
// serialize_member.cpp
// ----------------------------------------------------------------------------
#include <fw/base/core/macros.h>
#include <fw/base/serialize/serialize_member.h>
#include <fw/base/serialize/serialize_instance_member.h>
#include <fw/base/serialize/serialize_counted_pointer_member.h>
#include <fw/base/serialize/serialize_string_pointer_member.h>
#include <fw/base/serialize/serialize_scalar_type.h>
#include <fw/base/serialize/byte_reader.h>
#include <fw/base/serialize/byte_writer.h>

namespace fw
{
	SerializeMember::SerializeMember(int count, Hash typeName)
	: m_typename(typeName)
	, m_offset	(0)
	, m_scope	(nullptr)
	, m_type	(nullptr)
	, m_count	(count)
	{
	}
	
	SerializeMember::~SerializeMember()
	{
	}
	
	void SerializeMember::SetScope(const SerializeCompoundType *scope)
	{
		m_scope = scope;
	}
	
	char* SerializeMember::GetDataPtr(char *scopeData, int index) const
	{
		return (scopeData) ? (scopeData + m_offset + index * GetSize()) : nullptr;
	}
	
	const char* SerializeMember::GetDataPtr(const char *scopeData, int index) const
	{
		return (scopeData) ? (scopeData + m_offset + index * GetSize()) : nullptr;
	}
	
	SerializeScalarValue SerializeMember::ReadScalarValue(const char *scopeData) const
	{
		const SerializeScalarType* scalarType = m_type->AsScalarType();
		return scalarType->ReadScalarValue(scopeData + m_offset);
	}
	
	size_t SerializeMember::GetTotalSize() const
	{
		return GetSize() * m_count;
	}
	
	SerializeStatus SerializeMember::FixUp(SerializeSchema &schema, const SerializeMember* previousMember)
	{
		m_type = PreFixUp(schema, m_typename);
		
		size_t offset = previousMember ? previousMember->m_offset + previousMember->GetTotalSize() : 0;
		offset		  = FW_ALIGNMENT(offset, GetAlignment());
		m_offset      = offset;
		
		return kStatus_Ok;
	}
	
	SerializeMember* SerializeMember::ReadNew(ByteReader &reader)
	{
		SerializeMember* member = nullptr;
		if(!member) member = reader.ReadNew<SerializeInstanceMember>();
		if(!member) member = reader.ReadNew<SerializeCountedPointerMember>();
		if(!member) member = reader.ReadNew<SerializeStringPointerMember>();
		return member;
	}

	uint64_t SerializeMember::GetChecksum(uint64_t basis) const
	{
		basis = HashValue64(m_typename, basis);
		basis = HashValue64(m_offset,   basis);
		basis = HashValue64(m_count,    basis);
		return basis;
	}
	
} // namespace fw
